package com.aliyun.messagemgt.service;

import com.aliyun.messagemgt.common.constant.CommonConstant;
import com.aliyun.messagemgt.common.constant.DingConstant;
import com.aliyun.messagemgt.common.enums.PushResultEnum;
import com.aliyun.messagemgt.common.dto.send.*;
import com.aliyun.messagemgt.common.enums.ChannelTypeEnum;
import com.aliyun.messagemgt.sendplugin.SendStrategy;
import com.aliyun.messagemgt.sendplugin.SendStrategyFactory;
import com.aliyun.messagemgt.util.DingRobotSignUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.taobao.api.ApiException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DingRobotSendStrategy implements SendStrategy, InitializingBean {

    private static Logger logger = LoggerFactory.getLogger(DingRobotSendStrategy.class);

    @Value("${dingding.dingRobot.url}")
    private String dingRobotUrl;

    @Override
    public void afterPropertiesSet() {
        SendStrategyFactory.register(ChannelTypeEnum.DING_ROBOT.getType(), this);
    }

    @Override
    public void sendMessage(PushChannelInfo pushChannelInfo, MsgRecordVO msgRecordVO) {

        // 获取签名并校验
        long timestamp = System.currentTimeMillis();
        String sign = DingRobotSignUtil.getDingRobotSign(pushChannelInfo.getCorpSecret(), timestamp);
        List<Receiver> receivers = msgRecordVO.getReceivers();
        MsgMiddleResult msgMiddleResult = null;
        if (StringUtils.isEmpty(sign)) {
            msgMiddleResult = generateMsgMiddleResult(receivers, PushResultEnum.PUSH_SIGN_INVALID);
            msgRecordVO.getResults().add(msgMiddleResult);
            return;
        }

        try {
            // 推送钉钉机器人
            pushDingRobotMsg(pushChannelInfo, msgRecordVO, sign, timestamp);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("钉钉机器人推送消息出现错误 {}", e.toString());
            msgMiddleResult = generateMsgMiddleResult(receivers, PushResultEnum.PUSH_ERROR);
            msgRecordVO.getResults().add(msgMiddleResult);
        }
    }

    private void pushDingRobotMsg(PushChannelInfo pushChannelInfo, MsgRecordVO msgRecordVO, String sign, long timestamp) throws ApiException {
        String serviceUrl = dingRobotUrl + pushChannelInfo.getCorpId() + "&timestamp=" + timestamp + "&sign=" + sign;
        DingTalkClient client = new DefaultDingTalkClient(serviceUrl);
        OapiRobotSendResponse response = getDingRobotResponse(msgRecordVO, client);
        MsgMiddleResult msgMiddleResult;
        if (response.isSuccess()) {
            msgMiddleResult = generateMsgMiddleResult(msgRecordVO.getReceivers(), PushResultEnum.PUSH_SUCCESS);
        } else {
            msgMiddleResult = generateMsgMiddleResult(msgRecordVO.getReceivers(),
                    PushResultEnum.PUSH_ROBOT_ERROR_CODE.getErrorCode(), response.getErrmsg());
        }
        msgRecordVO.getResults().add(msgMiddleResult);
    }

    private OapiRobotSendResponse getDingRobotResponse(MsgRecordVO msgRecordVO, DingTalkClient client) throws ApiException {
        OapiRobotSendResponse response = null;
        OapiRobotSendRequest request = buildActioncardRequest(msgRecordVO);
        if (null != request) {
            response = client.execute(request);
        }
        request = buildFeedCardRequest(msgRecordVO);
        if (null != request) {
            response = client.execute(request);
            request = null;
        }
        List<MsgBody> contents = msgRecordVO.getContents();
        for (MsgBody msgBody : contents) {
            String type = msgBody.getType();
            if (DingConstant.ACTIONCARD.equals(type) || DingConstant.FEEDCARD.equals(type)) {
                continue;
            }
            request = new OapiRobotSendRequest();
            request.setMsgtype(type);
            switch (type) {
                case CommonConstant.TEXT:
                    OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
                    text.setContent(msgBody.getContent());
                    request.setText(text);
                    break;
                case DingConstant.MARKDOWN:
                    OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
                    markdown.setTitle(msgRecordVO.getMsgTitle());
                    markdown.setText(msgBody.getContent());
                    request.setMarkdown(markdown);
                    break;
                case DingConstant.LINK:
                    OapiRobotSendRequest.Link link = new OapiRobotSendRequest.Link();
                    link.setTitle(msgRecordVO.getMsgTitle());
                    link.setText(msgBody.getContent());
                    link.setPicUrl(msgBody.getPicUrl());
                    link.setMessageUrl(msgBody.getMessageUrl());
                    request.setLink(link);
                    break;
                default:
                    break;
            }

            setAtMobiles(request, msgRecordVO.getReceivers());
            response = client.execute(request);
        }
        return response;
    }

    private OapiRobotSendRequest buildFeedCardRequest(MsgRecordVO msgRecordVO) {
        List<MsgBody> contents = msgRecordVO.getContents();
        List<MsgBody> feedCardContents = contents.stream().filter(s -> DingConstant.FEEDCARD.equals(s.getType())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(feedCardContents)) {
            return null;
        }
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype(DingConstant.FEEDCARD);
        OapiRobotSendRequest.Feedcard feedcard = new OapiRobotSendRequest.Feedcard();
        OapiRobotSendRequest.Links link = null;
        List<OapiRobotSendRequest.Links> links = new ArrayList<>();
        for (MsgBody msgBody : feedCardContents) {
            link = new OapiRobotSendRequest.Links();
            link.setTitle(msgBody.getContent());
            link.setPicURL(msgBody.getPicUrl());
            link.setMessageURL(msgBody.getMessageUrl());
            links.add(link);
        }
        feedcard.setLinks(links);
        request.setFeedCard(feedcard);
        return request;
    }

    private OapiRobotSendRequest buildActioncardRequest(MsgRecordVO msgRecordVO) {
        List<MsgBody> contents = msgRecordVO.getContents();
        List<MsgBody> actionCardContents = contents.stream().filter(s -> DingConstant.ACTIONCARD.equals(s.getType())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(actionCardContents)) {
            return null;
        }
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype(DingConstant.ACTIONCARD);
        OapiRobotSendRequest.Actioncard actioncard = new OapiRobotSendRequest.Actioncard();
        actioncard.setTitle(msgRecordVO.getMsgTitle());
        actioncard.setBtnOrientation(msgRecordVO.getBtnOrientation());
        actioncard.setText(msgRecordVO.getMsgContent());
        if (actionCardContents.size() == 1) {
            MsgBody msgBody = actionCardContents.get(0);
            actioncard.setSingleTitle(msgBody.getContent());
            actioncard.setSingleURL(msgBody.getMessageUrl());
        } else {
            OapiRobotSendRequest.Btns btn = null;
            List<OapiRobotSendRequest.Btns> btns = new ArrayList<>();
            for (MsgBody msgBody : actionCardContents) {
                btn = new OapiRobotSendRequest.Btns();
                btn.setTitle(msgBody.getContent());
                btn.setActionURL(msgBody.getMessageUrl());
                btns.add(btn);
            }
            actioncard.setBtns(btns);
        }
        request.setActionCard(actioncard);
        return request;
    }

    private static void setAtMobiles(OapiRobotSendRequest request, List<Receiver> receivers) {
        List<String> keys = receivers.stream().map(Receiver::getReceiverMobilePhone).collect(Collectors.toList());
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        if (CollectionUtils.isNotEmpty(keys)) {
            at.setAtMobiles(keys);
            if (keys.contains(CommonConstant.ALL)) {
                at.setIsAtAll(true);
            }
        }
        request.setAt(at);
    }

    /**
     * 封装消息返回结果
     *
     * @param reveivers  接收人
     * @param pushResult 推送状态/描述
     */
    private MsgMiddleResult generateMsgMiddleResult(List<Receiver> reveivers, PushResultEnum pushResult) {
        return generateMsgMiddleResult(reveivers, pushResult.getErrorCode(), pushResult.getDescription());
    }

    /**
     * 封装消息返回结果
     *
     * @param reveivers             接收人
     * @param pushResultCode        推送状态码
     * @param pushResultDescription 推送结果描述
     */
    private MsgMiddleResult generateMsgMiddleResult(List<Receiver> reveivers, Integer pushResultCode, String pushResultDescription) {
        return new MsgMiddleResult()
                .setReceivers(reveivers)
                .setPushResultCode(pushResultCode)
                .setPushResultDescription(pushResultDescription);
    }
}
